<template>
  <div id="wrap" class="loaded">
    <div class="inner">
      <div v-for="(record, index) in records" :key="index" class="record" :class="{ current: currentIndex === index }"
           :style="{ backgroundImage: `url(${record.imgUrl})` }">
        <h2 :style="lineHeightStyle(record.name)" :data-text="record.name">{{ record.name }}</h2>
        <h2 :style="lineHeightStyle(record.singer)" :data-text="record.singer">{{ record.singer }}</h2>
        <img :src="record.imgUrl" alt=""/>

        <!-- 只在播放状态下显示暂停按钮 -->
        <span v-show="isPlaying && currentIndex === index" @click="pauseAudio" class="iconfont icon-weibiaoti--"></span>

        <!-- 只在暂停状态下显示播放按钮 -->
        <span v-show="!isPlaying || currentIndex !== index" @click="toggleAudio(index)"
              class="iconfont icon-bofang2"></span>

        <!-- 显示歌词 -->
        <div class="lyrics" v-if="record.lyrics">

        </div>
        <a class="info" target="_blank">Info</a>
      </div>
    </div>
    <div class="next" @click="nextRecord"></div>
    <div class="prev" @click="prevRecord"></div>
    <audio :src="records[currentIndex]?.audioUrl" ref="audio" style="opacity: 0;" @ended="onAudioEnd" controls></audio>
  </div>
</template>

<script setup lang="ts">
import {ref, watch, onMounted, Ref,} from 'vue';
import {getMusicData} from '@/api/request';

// 定义音乐数据接口
interface MusicData {
  name: string; // 音乐名称
  audioUrl: string; // 音频地址
  imgUrl: string; // 图片地址
  singer: string; // 歌手
  lyrics: string; // 歌词
}

// 定义音乐数据响应接口
interface MusicDataResponse {
  data: MusicData[]; // 音乐数据数组
}

// 数据
const records: Ref<MusicData[]> = ref([]);
const currentIndex = ref<number>(0);
const isPlaying = ref<boolean>(false);
const audio = ref<HTMLAudioElement | null>(null);

// 计算属性：根据文本内容判断是否为中文
const lineHeightStyle = (text: string) => {
  // 正则判断文本中是否有中文
  const isChinese = /[\u4e00-\u9fa5]/.test(text);
  // 根据是否为中文来返回不同的行高
  return {
    lineHeight: isChinese ? '1' : '0.75'
  };
};

// 切换音频播放状态
const toggleAudio = (index: number): void => {
  if (currentIndex.value === index && isPlaying.value) {
    pauseAudio();
  } else {
    currentIndex.value = index;
    playAudio();
  }
};

// 播放音频
const playAudio = (): void => {
  if (audio.value) {
    audio.value.play().then(() => {
      isPlaying.value = true;
    }).catch((err) => console.error('播放失败:', err));
  }
};

// 暂停音频
const pauseAudio = (): void => {
  if (audio.value) {
    audio.value.pause();
    isPlaying.value = false;
  }
};

// 音频播放结束
const onAudioEnd = (): void => {
  isPlaying.value = false;
  nextRecord();
};

// 切换到下一个专辑
const nextRecord = (): void => {
  if (records.value.length > 0) {
    currentIndex.value = (currentIndex.value + 1) % records.value.length;
  }
};

// 切换到上一个专辑
const prevRecord = (): void => {
  if (records.value.length > 0) {
    currentIndex.value = (currentIndex.value - 1 + records.value.length) % records.value.length;
  }
};

// 监听 currentIndex 变化，切换音频源并等待加载完成再播放
watch(currentIndex, (newIndex) => {
  if (audio.value && records.value.length > 0) {
    audio.value.pause();
    isPlaying.value = false;
    audio.value.src = records.value[newIndex].audioUrl;
    audio.value.oncanplaythrough = () => {
      playAudio();
    };
  }
});

onMounted(() => {
  getMusicData().then((res: MusicDataResponse) => {
    records.value = res.data;
  });
});
</script>


<style scoped lang="scss">
a {
  cursor: pointer;
}

$t: transparent;
$b: #222;


svg {
  position: absolute;
}

#wrap {
  position: relative;
  width: 100%;
  height: 100%;
  background: #222;
  z-index: 2;
  overflow: hidden;
  border-radius: 12px;

  .next,
  .prev {
    transition: all 300ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
  }

  * {
    opacity: 0;
    transition: 0.3s ease-in-out;
  }

  &.loaded {
    * {
      opacity: 1;
    }

    .next,
    .prev {
      transition-delay: 2s;
    }

    &:before {
      opacity: 0;
    }
  }

  .backdrop {
    position: absolute;
    width: calc(100% + 100px);
    height: calc(100% + 100px);
    left: -50px;
    top: -50px;
    z-index: 0;
    background-size: cover;
    background-position: center;
    filter: blur(10px);
  }

  .inner {
    position: absolute;
    width: 400px;
    height: 400px;
    left: calc(50% - 200px);
    top: calc(50% - 200px);
    transition: all 300ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
    z-index: 2;

    .record {
      width: 400px;
      height: 400px;
      position: absolute;
      left: 0;
      top: 0;
      z-index: 8;
      display: flex;
      align-items: center;
      justify-content: center;
      transform-origin: bottom;
      background-size: 0px;

      &:nth-of-type(odd) {
        h2 {
          filter: url(#wave2);
        }
      }

      h2 {
        position: absolute;
        font-size: 80px;
        display: block;
        text-align: left;
        top: -25%;
        line-height: 0.75;
        margin: 0;
        color: transparent;
        max-width: 400px;
        padding: 10px;
        overflow: hidden;
        left: calc(50% - 300px);
        filter: url(#wave);
        z-index: 9;
        transform: scaleY(1.25);
        transform-origin: bottom;

        &.small {
          font-size: 75px;
        }

        &:nth-of-type(2) {
          top: 90%;
          left: 50%;
          font-size: 50px;
          text-align: right;

          &.small {
            font-size: 50px;
          }

          &:before,
          &:after {
            left: 50%;
          }

          &:after {
            transform-origin: left;
          }
        }

        &:before,
        &:after {
          content: attr(data-text);
          color: #fff;
          position: absolute;
          left: 50%;
          bottom: 5px;
          transition: 0.3s ease-in-out;
          transform: translateX(-50%) translateY(150%);
          display: inline-block;
          width: 100%;
        }

        &:after {
          transform-origin: right;
          color: transparent;
          transform: none;
          bottom: 0px;
          border-bottom: 5px solid #fff;
          padding-bottom: 3px;
          transform: translateX(-50%) scaleX(0);
          transition: 0.4s ease-in-out;
        }
      }

      &:before {
        content: "";
        position: absolute;
        width: 100vw;
        height: 100vh;
        background-image: inherit;
        background-size: cover;
        background-position: center;
        z-index: -1;
        filter: blur(10px);
        opacity: 0;
        transition: opacity 1s ease-in-out, transform 3s ease-in-out;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%) scale(1.5);
      }

      &.current {
        z-index: 10;

        & ~ .record {
          img {
            clip-path: polygon(0 0, 100% 0, 100% 0, 0 0);
          }
        }

        a.info {
          transform: scale(1) rotate(0deg);
          transition-delay: 2s;
        }

        a:not(.info) {
          transform: scale(1);
          transition-delay: 1.5s;
        }

        h2 {
          &:before {
            left: 50%;
            transition-delay: 1s;
            transform: translateX(-50%) translateY(0);
          }

          &:after {
            transition-delay: 0.6s;
            transform: translateX(-50%) scaleX(1);
            animation: scaleOut 0.4s ease-in-out 1 forwards;
            animation-delay: 1.3s;

            @keyframes scaleOut {
              from {
                transform-origin: left;
                transform: translateX(-50%) scaleX(1);
              }

              to {
                transform-origin: left;
                transform: translateX(-50%) scaleX(0);
              }
            }
          }

          &:nth-of-type(2) {
            &:before {
              transition-delay: 1.2s;
            }

            &:after {
              transition-delay: 0.8s;
              animation: scaleOut2 0.4s ease-in-out 1 forwards;
              animation-delay: 1.5s;

              @keyframes scaleOut2 {
                from {
                  transform-origin: right;
                  transform: translateX(-50%) scaleX(1);
                }

                to {
                  transform-origin: right;
                  transform: translateX(-50%) scaleX(0);
                }
              }
            }
          }
        }

        img {
          clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%);
          transition-delay: 0.3s;
        }

        &:before {
          opacity: 0.75;
          transform: translate(-50%, -50%) scale(1);
        }
      }

      img {
        width: 112.5%;
        height: 112.5%;
        object-fit: cover;
        clip-path: polygon(0 100%, 100% 100%, 100% 100%, 0 100%);
        transition: clip-path 0.3s ease-in-out;
        z-index: -1;
      }

      a.info {
        position: absolute;
        width: 50px;
        height: 50px;
        background-image: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/383755/bc.png");
        background-size: 60%;
        background-repeat: no-repeat;
        background-position: center;
        bottom: -50px;
        left: -50px;
        border-radius: 100%;
        filter: invert(1);
        cursor: pointer;
        box-shadow: 0 0 0 3px #000;
        z-index: 9;
        transition: transform 300ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
        transform: scale(0) rotate(-90deg);

        &.spotify {
          background-image: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/383755/spotify.png");
          background-size: 80%;
        }

        &:hover {
          background-color: rgba(255, 255, 255, 0.25);
        }
      }

      .iconfont {
        font-size: 50px;
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
        cursor: pointer;
        color: white;
      }

      .icon-bofang2 {
        font-size: 53px;
      }
    }
  }
}

iframe {
  opacity: 0;
  width: 0;
  height: 0;
  z-index: -9999;
  position: absolute;
}

.next,
.prev {
  width: 50px;
  height: 50px;
  z-index: 999;
  position: absolute;
  top: calc(50% - 25px);
  left: calc(50% + 325px);
  cursor: pointer;
  transform: scaleY(1);
  transition: all 100ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
  transition-delay: 0.5s;

  &:before {
    content: "";
    position: absolute;
    width: 50%;
    height: 50%;
    left: 0;
    top: 25%;
    background: linear-gradient(-45deg, $t 50%, #fff 50%);
    transform: rotate(135deg);
  }
}

.prev {
  right: auto;
  left: calc(50% - 350px);

  &:before {
    transform: rotate(-45deg);
  }
}
</style>
